from apiflask import input, output, abort, APIBlueprint, auth_required
from flask.globals import g
from apiflask.decorators import doc
from flask.helpers import send_file, send_from_directory
from flask.views import MethodView
from sqlalchemy.sql.functions import user
# import my app
from app.extensions import auth, db

from app.schemas import make_res
from app.schemas.auth import UserLoginInSchema, RegUserInSchema, RegUserOutSchema
from app.models import User
# from app.models import User

auth_bp = APIBlueprint('auth', __name__)

@auth_bp.route('/')
class LoginView(MethodView):

    @auth_required(auth)
    @doc(description="登录测试接口")
    def get(self):
        return {'msg': f'{g.username} was login!'}

    @input(UserLoginInSchema)
    @doc(summary='用户登录接口', description="用户登录接口-POST方法", tag='Auth')
    def post(self, data):
        try:
            token = self._login(data.get('username'), data.get('password'))
            return make_res(detal={
                "token": token
            })
        except ValueError as ve:
            abort(401, message=str(ve))
        except Exception as e:
            abort(500)
    
    @staticmethod
    def _login(username:str, password:str) -> str:
        """A login function.
            
            Arguments:
                username: login username
                password: login user password
            
            return:
                token: the user login token of authority.
        """
        if username is None or password is None:
            raise ValueError("用户名或密码未输入")
        
        user:User = User.query.filter(User.username == username).first()
        if user is None:
            raise ValueError('用户未注册')
        if not user.validate_password(password):
            raise ValueError('密码错误')
        else:
            token:str = user.generate_auth_token()
            return token

@auth_bp.route('/reg')
class RegUserView(MethodView):

    @input(RegUserInSchema)
    @output(RegUserOutSchema)
    def post(self, data):
        print(data, type(data))
        try:
            user = self._reg(data)
            return user
        except ValueError as ve:
            abort(409, message=str(ve))
        except Exception as e:
            abort(500, message=str(e))
    
    @staticmethod
    def _reg(reg_data:dict):
        user = User.query.filter(User.username == reg_data.get('username')).first() \
        or User.query.filter(User.phone == reg_data.get('phone')).first()  \
        or User.query.filter(User.email == reg_data.get('email')).first()

        # print(user)
        if user is not None:
            raise ValueError('用户已注册')
        try:
            user = User()
            user.username = reg_data.get('username')
            user.set_password = reg_data.get('password')
            user.phone = reg_data.get('phone')
            user.email = reg_data.get('email')
            user.sex = reg_data.get('sex')
            user.grad = reg_data.get('grad')
            user.personal_sign = reg_data.get('personal_sign')
            db.session.add(user)
            db.session.commit()
            return user
        except Exception as e:
            db.session.rollback()
            raise e

